# -*- coding: utf-8 -*-

 ###############################################
 ##                                             ##
 ##   Submódulo modelo                           ##
 ##   @ Módulo servicios                         ##
 ##                                              ##
 ##   de la línea Básicos                        ##
 ##   de Críptidos Digitales                     ##
 ##   GPL (c)2008                                ##
  ##                                             ##
    ###############################################

# print (0), "  servicios.manejador   begin"

from sqlalchemy import desc, sql
# from man import Acepcion, Atributo, Documento, Entidad, Equipo, PartidaDocumento, Proceso, Producto, Servicio, Rol
from man import *

import man

# print (0), "  servicios.manejador     definitions"


def recepcionI(data):
    ##    Cliente
    if type(data['cliente']) == dict:
        data['cliente']['tipo'] = u"cliente"
        cliente = rolI(**data['cliente'])
    else:
        cliente = data.pop('cliente')


    if type(data['equipo']) == dict:

        data['equipo']['propietario_id'] = cliente.id

        if 'marca' in data['equipo'].keys():
            data['equipo']['marca_id'] = man.atributoI(grupo=u'marcaEquipo', nombre=data['equipo'].pop('marca')).id

        if 'linea' in data['equipo'].keys():
            data['equipo']['linea_id'] = man.atributoI(grupo=u'lineaEquipo', nombre=data['equipo'].pop('linea'), referencia=u'%s' % data['equipo']['marca_id']).id

        if 'modelo' in data['equipo'].keys():
            data['equipo']['modelo_id'] = man.atributoI(grupo=u'modeloEquipo', nombre=data['equipo'].pop('modelo'), referencia=u'%s' % data['equipo']['linea_id']).id

        equipo = Equipo(**data['equipo'])
        man.session().add(equipo)
        man.session().flush()
    else:
        equipo = data.pop('equipo')

    # Proceso - Se asumió que no hay proceso creado para esta transacción
    #    Determinación de status de Proceso




    status = u'abierto'

    if 'proceso' in data.keys():
        proceso = data['proceso']
    else:
        # Se omite la fecha para que se capture el momento de captura
        proceso = Proceso(tipo=u'servicio', status=status)
        man.session().add(proceso)
        man.session().flush()

    ## Operación de Recepción, no afecta cuenta
    operacion = Operacion(tipo=u'recepción', cuenta=u'', fecha=data['fecha'], status=status)
    proceso.operaciones.append(operacion)
    man.session().add(operacion)
    man.session().flush()

    ## Documento de Servicio
    tipoDocumento = man.atributoI(grupo=u'tipoDocumento', nombre=u'servicio')
    documento = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id, folio=data['folio'], fecha=data['fecha'], rol_id=cliente.id, status=status)
    man.session().add(documento)
    man.session().flush()

    ## Actualiza Folio
    registro = atributoI(grupo=u'folioDocumento', nombre=u'servicio', valor=unicode(data['folio']))

    ## Documento de complemento
    servicio = Servicio(documento_id=documento.id, equipo_id=equipo.id, accesorios=data['accesorios'], nivel1=data['nivel1'], nivel2=data['nivel2'], sintomas=data['sintomas'])
    man.session().add(servicio)
    man.session().flush()

    man.session().commit()

    return proceso


def agregaDiagnostico(data):
    documento = [x.documentos[0] for x in data['proceso'].operaciones if x.tipo==u'recepción'][0]

    servicio = dameServicio(documento_id=documento.id)
    servicio.fechadiagnostico = data['fecha']
    servicio.tecnico_id = data['tecnico_id']
    servicio.diagnostico = data['diagnostico']
    man.session().commit()


def agregaPresupuesto(data):
    m = "servicios.manejador.agregaPresupuesto()"

    """ Se usa el mismo cliente de la recepción """
    clienteId = [x.documentos[0] for x in data['proceso'].operaciones if x.tipo==u'recepción'][0].rol_id

    ## Operacion de solicitud
    operacion = operacionI(tipo=u'solicitud', cuenta=u'inventarios', fecha=data['fecha'], monto=data['total'], status=u'abierta', proceso=data['proceso'])

    ## Documento
    tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=u'pedido')

    pedido = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id, folio=data['folio'], fecha=data['fecha'], rol_id=clienteId, subtotal=data['subtotal'], descuento=data['descuento'], impuesto=data['impuesto'], total=data['total'], status=u'abierto')
    man.session().add(pedido)
    man.session().flush()

    ## Partidas
    for partida in data['partidas']:
        partida = PartidaDocumento(documento_id=pedido.id, producto_id=partida['producto_id'], cantidad=partida['cantidad'], costo=partida['costo'], precio=partida['precio'], descuento=partida['descuento'], impuesto=partida['impuesto'], status=u'abierta')
        pedido.partidas.append(partida)
        man.session().add(partida)
    man.session().flush()

    man.session().commit()

    ## Actualiza folio
    registro = atributoI(grupo=u'folioDocumento', nombre=u'pedido', valor=data['folio'])

    return pedido


def agregaVenta(data):
    m = "servicios.manejador.agregaVenta()"

    """ Se usa el mismo cliente de la recepción """
    clienteId = [x.documentos[0] for x in data['proceso'].operaciones if x.tipo==u'recepción'][0].rol_id

    if 'pago' in data.keys():
        status = u'cerrado'
        statusPartidas= u'cerrada'
    else:
        status = u'abierto'
        statusPartidas = u'abierta'

    ## Documento
    venta = Documento(tipo_id=data['tipoDocumento_id'], folio=data['folio'], fecha=data['fecha'], rol_id=clienteId, subtotal=data['subtotal'], descuento=data['descuento'], descuentoporcentaje=data['descuentoPorcentaje'], impuesto=data['impuesto'], impuestoporcentaje=data['impuestoPorcentaje'], total=data['total'], status=status)
    man.session().add(venta)
    man.session().flush()

    costoTotal = dec('0.00')

    ## Partidas
    for partida in data['partidas']:
        partida = PartidaDocumento(documento_id=venta.id, producto_id=partida['producto_id'], cantidad=partida['cantidad'], costo=partida['costo'], precio=partida['precio'], descuento=partida['descuento'], impuesto=partida['impuesto'], status=statusPartidas)
        venta.partidas.append(partida)
        man.session().add(partida)
    man.session().flush()

    ## Operacion (se crea despues de calcular el costoTotal)
    operacion = operacionI(cuenta=u'inventarios', tipo=u'salida', fecha=data['fecha'], monto=-costoTotal, status=u'cerrada', proceso=data['proceso'])

    venta.operacion_id = operacion.id
    man.session().add(venta)

    man.session().flush()


    if data['pago']:

        pago = data['pago']

        if pago['tipo'] == u'efectivo':
            operacion = operacionI(cuenta=u'caja', tipo=u'cobro', fecha=datetime.datetime.today(), monto=pago['total'], status=u'cerrada', proceso=data['proceso'])

            tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=pago['tipo'])

            documento = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id,  rol_id=clienteId, total=pago['total'], subtotal=pago['recibido'], descuento=pago['cambio'], fecha=datetime.datetime.today(), status=u'cerrado')
            man.session().add(documento)
            man.session().flush()

        consolidaSalidas(venta.partidas)

        ## Actualiza folio
        if venta.tipo.nombre == u'remisión':
            registro = atributoI(grupo=u'folioDocumento', nombre=u'ventaControl', valor=unicode(data['folio']))
        elif venta.tipo.nombre == u'factura':
            registro = atributoI(grupo=u'folioDocumento', nombre=u'ventaFiscal', valor=unicode(data['folio']))

    man.session().commit()

    return venta


def agrega(data):
    ##    Cliente
    if type(data['recepcion']['cliente']) == dict:
        data['recepcion']['cliente']['tipo'] = u"cliente"
        # if 'telefono' in data['recepcion']['cliente']:
            # data['recepcion']['cliente']['tipocontacto'] = u'Tel fijo'
            # data['recepcion']['cliente']['valorcontacto'] = data['recepcion']['cliente'].pop('telefono')
        cliente = rolI(**data['recepcion']['cliente'])
    else:
        cliente = data['recepcion'].pop('cliente')

    ##    Equipo
    if type(data['recepcion']['equipo']) == dict:
        # EQUIPO ( id, tipo, serie, clave2, color, origen, propietario_id, accesorios, observaciones )
        data['recepcion']['equipo']['propietario_id'] = cliente.id
        equipo = Equipo(**data['recepcion']['equipo'])
        man.session().add(equipo)
    else:
        equipo = data['recepcion'].pop('equipo')

    ## Proceso - Se asumió que no hay proceso creado para esta transacción
    ##    Determinación de status de Proceso
    status = u'abierto'
    if 'venta' in data.keys():
        if 'pago' in data['venta'].keys():
            status = u'cerrado'

    proceso = Proceso(tipo=u'servicio', fecha=data['recepcion']['fecha'], status=status)
    man.session().add(proceso)
    man.session().flush()

    ## Operación de Recepción, no afecta cuenta
    operacion = Operacion(tipo=u'recepción', cuenta=u'', fecha=data['recepcion']['fecha'], status=status)
    proceso.operaciones.append(operacion)
    man.session().add(operacion)
    man.session().flush()

    ## Documento de Servicio
    tipoDocumento = man.atributoI(grupo=u'tipoDocumento', nombre=u'servicio')
    documento = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id, folio=data['folio'], fecha=data['recepcion']['fecha'], rol_id=cliente.id, status=status)
    man.session().add(documento)
    man.session().flush()

    ## Actualiza Folio
    registro = atributoI(grupo=u'folioDocumento', nombre=u'servicio', valor=unicode(data['folio']))

    ## Documento de complemento
    servicio = Servicio(documento_id=documento.id, equipo_id=equipo.id, accesorios=data['recepcion']['accesorios'], nivel1=data['recepcion']['nivel1'], nivel2=data['recepcion']['nivel2'], sintomas=data['recepcion']['sintomas'], fechadiagnostico=data['diagnostico']['fecha'], tecnico_id=data['diagnostico']['tecnico_id'], diagnostico=data['diagnostico']['diagnostico'])
    man.session().add(servicio)
    man.session().flush()

    # SERVICIO ( id, documento_id, equipo_id, nivel1, nivel2, accesorios, observaciones, sintomas, fechadiagnostico, tecnico_id, diagnostico )
    # servicio = {'documento_id':documento.id, 'equipo_id':equipo.id, 'accesorios':data['recepcion']['accesorios'], 'nivel1':data['recepcion']['nivel1'], 'nivel2':data['recepcion']['nivel2', 'sintomas':data['recepcion']['sintomas']}
    # if 'diagnóstico' in data.keys():
        # servicio['fechadiagnostico'] = data['diagnostico']['fecha']
        # servicio['tecnico_id'] = data['diagnostico']['tecnico_id']
        # servicio['diagnostico'] = data['diagnostico']['diagnostico']
    # servicio = Servicio(**servicio)

    ## Pedido (Presupuesto)
    if 'pedido' in data.keys():
        if data['pedido']['partidas']:     # Se checa validez de pedido

            ## Operacion de solicitud
            operacion = Operacion(tipo=u'solicitud', cuenta=u'inventarios', fecha=data['pedido']['fecha'], monto=data['pedido']['total'], status=u'abierta')
            proceso.operaciones.append(operacion)
            man.session().add(operacion)
            man.session().flush()

            ## Documento
            tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=u'pedido')
            pedido = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id, folio=data['pedido']['folio'], fecha=data['pedido']['fecha'], rol_id=cliente.id, subtotal=data['pedido']['subtotal'], descuento=data['pedido']['descuento'], impuesto=data['pedido']['impuesto'], total=data['pedido']['total'], status=u'abierto')
            man.session().add(pedido)
            man.session().flush()

            ## Pedido - partidas
            for partida in data['pedido']['partidas']:
                partida = PartidaDocumento(documento_id=pedido.id, producto_id=partida['producto_id'], cantidad=partida['cantidad'], costo=partida['costo'], precio=partida['precio'], descuento=partida['descuento'], impuesto=partida['impuesto'], status=u'abierta')
                pedido.partidas.append(partida)
                man.session().add(partida)
            man.session().flush()

            ## Actualiza folio
            registro = atributoI(grupo=u'folioDocumento', nombre=u'pedido', valor=data['pedido']['folio'])


    ## Venta
    if 'venta' in data.keys():
        if 'pago' in data['venta'].keys():
            status = u'cerrado'
            statusPartidas= u'cerrada'
        else:
            status = u'abierto'
            statusPartidas = u'abierta'

        if data['venta']['partidas']:

            ## Venta - documento
            venta = Documento(tipo_id=data['venta']['tipoDocumento_id'], folio=data['venta']['folio'], fecha=data['venta']['fecha'], rol_id=cliente.id, subtotal=data['venta']['subtotal'], descuento=data['venta']['descuento'], descuentoporcentaje=data['venta']['descuentoPorcentaje'], impuesto=data['venta']['impuesto'], impuestoporcentaje=data['venta']['impuestoPorcentaje'], total=data['venta']['total'], status=status)
            man.session().add(venta)
            man.session().flush()

            costoTotal = dec('0.00')

            ## Venta - partidas
            for partida in data['venta']['partidas']:
                partida = PartidaDocumento(documento_id=venta.id, producto_id=partida['producto_id'], cantidad=partida['cantidad'], costo=partida['costo'], precio=partida['precio'], descuento=partida['descuento'], impuesto=partida['impuesto'], status=statusPartidas)
                venta.partidas.append(partida)
                man.session().add(partida)
            man.session().flush()

            ## Venta - operacion (se crea despues de calcular el costoTotal)
            operacion = Operacion(cuenta=u'inventarios', tipo=u'salida', fecha=data['venta']['fecha'], monto=-costoTotal, status=u'cerrada')
            proceso.operaciones.append(operacion)
            man.session().add(operacion)

            venta.operacion_id = operacion.id
            man.session().add(venta)
            man.session().flush()


        if data['venta']['pago']:

            pago = data['venta']['pago']

            if pago['tipo'] == u'efectivo':
                operacion = operacionI(cuenta=u'caja', tipo=u'cobro', fecha=datetime.datetime.today(), monto=pago['total'], status=u'cerrada', proceso=proceso)
                # proceso.operaciones.append(operacion)
                # man.session().add(operacion)
                # man.session().flush()

                tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=pago['tipo'])

                documento = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id,  rol_id=pago['rol_id'], total=pago['total'], subtotal=pago['recibido'], descuento=pago['cambio'], fecha=datetime.datetime.today(), status=u'cerrado')
                man.session().add(documento)
                man.session().flush()



            """
            ## PAGO
            if data['pago']:
                formasPago = formasPagoI()
                tipo = int(data['pago'].split('|').pop(0))

                if formasPago[tipo].valor==u'efectivo':
                    operacion = Operacion(cuenta=u"caja", tipo=u'cobro', fecha=data['fecha'], monto=data['total'], status=u'cerrada', referencia=data['pago'])
                    proceso.operaciones.append(operacion)
                    man.session().add(operacion)
                    proceso.status = u'cerrado'

                elif formasPago[tipo].valor==u'cheque':
                    operacion = Operacion(cuenta=u"caja", tipo=u'cobro', fecha=data['fecha'], monto=data['total'], status=u'cerrada', referencia=data['pago'])
                    proceso.operaciones.append(operacion)
                    man.session().add(operacion)
                    proceso.status = u'cerrado'

                elif formasPago[tipo].valor==u'crédito':
                    operacion = Operacion(cuenta=u"pasivos", tipo=u'cobro', fecha=data['fecha'], monto=data['total'], status=u'cerrada', referencia=data['pago'])
                    proceso.operaciones.append(operacion)
                    man.session().add(operacion)
                    proceso.status = u'abierto'
            """

            consolidaSalidas(venta.partidas)

            ## Actualiza folio
            if venta.tipo.nombre == u'remisión':
                registro = atributoI(grupo=u'folioDocumento', nombre=u'ventaControl', valor=unicode(data['venta']['folio']))
            elif venta.tipo.nombre == u'factura':
                registro = atributoI(grupo=u'folioDocumento', nombre=u'ventaFiscal', valor=unicode(data['venta']['folio']))

    man.session().commit()

    return proceso


def consolidaSalidas(partidas):
    for partida in partidas:
        producto = dameProducto(id=partida.producto_id)
        if producto.actual:
            producto.actual -= partida.cantidad
        else:
            producto.actual = partida.cantidad
    man.session().flush()


def dameAcepcion(**filtros):
    if not filtros.has_key('status'):
        filtros['status'] = u'actual'
    registro = man.session().query(Acepcion).filter_by(**filtros).one()
    return registro


def dameAcepciones(**filtros):      # print "manejador.dameAcepciones()"
    registros = []
    if 'status' not in filtros.keys():
        filtros['status'] = u'actual'

    if filtros.has_key('rol_id'):
        if filtros.has_key('clasificacion'):
            if filtros.has_key('nombre'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'].lower())).filter(Acepcion.rol_id==filtros['rol_id']).join(Producto).filter(Producto.clasificacion==unicode(filtros['clasificacion'])).order_by(Acepcion.nombre).all()
            elif filtros.has_key('codigo'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'].lower())).filter(Acepcion.rol_id==filtros['rol_id']).join(Producto).filter(Producto.clasificacion==filtros['clasificacion']).order_by(Acepcion.codigo).all()
        else:
            if filtros.has_key('nombre'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'].lower())).filter(Acepcion.rol_id==filtros['rol_id']).order_by(Acepcion.nombre).all()
            elif filtros.has_key('codigo'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'].lower())).filter(Acepcion.rol_id==filtros['rol_id']).order_by(Acepcion.codigo).all()
    else:
        if filtros.has_key('clasificacion'):
            if filtros.has_key('nombre'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'].lower())).join(Producto).filter(Producto.clasificacion==filtros['clasificacion']).order_by(Acepcion.nombre).all()
            elif filtros.has_key('codigo'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'].lower())).join(Producto).filter(Producto.clasificacion==filtros['clasificacion']).order_by(Acepcion.codigo).all()
        else:
            if filtros.has_key('nombre'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'].lower())).order_by(Acepcion.nombre).all()
            elif filtros.has_key('codigo'):
                registros = man.session().query(Acepcion).filter(Acepcion.status==filtros['status']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'].lower())).order_by(Acepcion.codigo).all()
    return registros


def dameClasificaciones(**filtros):
    if 'nombre' in filtros.keys():
        registros = man.session().query(Atributo).filter(Atributo.propietario==u'productos').filter(Atributo.nombre==u'clasificacion').filter(Atributo.valor.like("%s%%" % unicode(filtros['nombre']))).all()
    return registros


def dameCliente(**filtros):
    registro = rolI(id=filtros['id'])
    return registro


def dameClientes(**filtros):
    f=g

    if filtros:
        registros = man.session().query(Rol).filter(Rol.tipo==u'cliente').join(Rol.entidad).filter(Entidad.nombre.like("%s%%" % filtros['nombre'])).all()
    else:
        registros = man.session().query(Rol).filter(Rol.tipo==u'cliente').all()
    return registros


def dameClientesDeServicio(**filtros):
    tipoRol_id = atributoI(grupo=u'tipoRol', nombre=u'cliente').id
    tipoDocumento_id = atributoI(grupo=u'tipoDocumento', nombre=u'servicio').id
    if filtros:
        registros = man.session().query(Rol).filter(Rol.tipo_id==tipoRol_id).join(Rol.entidad).filter(Entidad.nombre.like("%s%%" % filtros['nombre'])).all()
    else:
        registros = man.session().query(Rol).filter(Rol.tipo_id==tipoRol_id).join(Documento).filter(Documento.tipo_id==tipoDocumento_id).all()
    return registros


def condicionesPago():
    registros = atributosI(grupo=u'condicionesPago')
    return registros


def dameDocumento(**filtros):
    registro = man.session().query(Documento).filter_by(**filtros).first()
    return registro


def dameDocumentos(**filtros):
    registros = man.session().query(Documento).filter_by(**filtros).all()
    return registros


def dameEquipo(**filtros):
    registro = man.session().query(Equipo).filter(Equipo.id==filtros['id']).one()
    return registro


def dameEquipos(**filtros):         # print "servicios.manejador.dameEquipos()"
    if filtros:
        if 'propietario' in filtros.keys():
            if 'tipo' in filtros.keys():
                registros = man.session().query(Equipo).filter(Equipo.propietario_id==filtros['propietario']).filter(Equipo.tipo.like("%s%%" % filtros['tipo'])).all()
            else:
                registros = man.session().query(Equipo).filter(Equipo.propietario_id==filtros['propietario']).all()
        else:
            registros = man.session().query(Equipo).filter(Equipo.tipo.like("%s%%" % filtros['tipo'])).all()
    else:
        registros = man.session().query(Equipo).all()
    return registros


def dameFolio():
    folio = int(atributoI(grupo=u'folioDocumento', nombre=u'servicio').valor)
    folio += 1
    return str(folio).zfill(4)


def dameFolioPresupuesto():
    folio = int(atributoI(grupo=u'folioDocumento', nombre=u'presupuesto').valor)
    folio += 1
    return str(folio).zfill(4)


def dameFolioVenta(tipoDocumento_id):
    m = "servicios.manejador.dameFolioVenta()"

    tipoDocumento = man.atributoI(id=tipoDocumento_id)

    if tipoDocumento.nombre == u'factura':
        folio = int(atributoI(grupo=u'folioDocumento', nombre=u'ventaFiscal').valor)
    elif tipoDocumento.nombre == u'remisión':
        folio = int(atributoI(grupo=u'folioDocumento', nombre=u'ventaControl').valor)
    folio += 1
    return str(folio).zfill(4)


def formasPagoI():
    registros = atributosI(grupo=u'formaPago', order=u'referencia')
    return registros


def dameLineas(**filtros):
    if 'marca' in filtros.keys():
        registros = atributosI(grupo=u'lineaEquipo', referencia=u'%s' % filtros['marca'], order=u'nombre')
    else:
        registros = atributosI(grupo=u'lineaEquipo', order=u'nombre')
    return registros


def dameMarcas(**filtros):
    registros = atributosI(grupo=u'marcaEquipo', order=u'nombre')
    return registros


def dameModelos(**filtros):
    if 'linea' in filtros.keys():
        registros = atributosI(grupo=u'modeloEquipo', referencia=u'%s' % filtros['linea'], order=u'nombre')
    else:
        registros = atributosI(grupo=u'modeloEquipo', order=u'nombre')
    return registros


# def dameOperacion(**filtros):
    # if 'proceso_id' in filtros.keys():
        # procesoId = filtros.pop('proceso_id')
        # registro = man.session().query(Operacion).filter_by(**filtros).join(Proceso).filter(Proceso.id==procesoId).first()
    # else:
        # registro = man.session().query(Operacion).filter_by(**filtros).first()
    # return registro


def damePartida(**filtros):
    registro = man.session().query(PartidaDocumento).filter_by(**filtros).first()
    return registro


def dameProducto(**filtros):
    registro = man.session().query(Producto).filter(Producto.id==filtros['id']).one()
    return registro


def dameProductos(filtros={}):
    m = "servicios.manejador.dameProductos()"

    registros = []
    if filtros.has_key('origen'):
        registros = man.session().query(Producto).filter(Producto.nombre.like("%s%%" % filtros['nombre'])).filter(Producto.origen==filtros['origen']).all()
    else:
        registros = man.session().query(Producto).filter(Producto.nombre.like("%s%%" % filtros['nombre'])).all()
    return registros


def rangosPrecio():
    registros = atributosI(grupo=u'rangoPrecioProducto', order=u'referencia')
    return registros


def dameServicio(**filtros):
    registro = man.session().query(Servicio).filter(Servicio.documento_id==filtros['documento_id']).one()
    return registro


def dameStatuss(**filtros):
    registros = atributosI(grupo=u'procesos', nombre=u'status')
    return registros


def dameTecnico(**filtros):
    registro = rol(id=filtros['id'])
    return registro


def dameTecnicos(**filtros):        # print "servicios.manejador.dameTecnicos()"
    tipoRol = man.atributoI(grupo=u'tipoRol', nombre=u'empleado')
    registros = rolesI(tipo_id=tipoRol.id, funcion=u'técnico')
    return registros


def dameTiposDocumentoVenta():
    registros = man.session().query(Atributo).filter(Atributo.grupo==u'tipoDocumento').filter(Atributo.referencia.like(u'%venta%')).all()
    return registros


def dameTipoDocumentoVentaDefault():
    registro = atributoI(grupo=u'tipoDocumentoVenta', nombre=u'default')
    return int(registro.valor)


def dameUltimoServicio(**filtros):
    registro = man.session().query(Servicio).filter(Servicio.equipo_id==filtros['equipo']).join(Documento).order_by(desc(Documento.fecha)).first()
    return registro


def servicioI(**filtros):
    if 'folio' in filtros:
        tipoDocumento = man.atributoI(grupo=u'tipoDocumento', nombre=u'servicio')
        operacion = man.session().query(Operacion).join(Documento).filter(Documento.tipo_id==tipoDocumento.id).filter(Documento.folio==filtros['folio']).first()
        if operacion:
            proceso = man.session().query(Proceso).filter(Proceso.operaciones.any(id=operacion.id)).one()
            return proceso
    elif 'id' in filtros:
        proceso = man.session().query(Proceso).filter(Proceso.id==filtros['id']).one()
        return proceso


def dameUno(**filtros):
    """ Regresa el Proceso que cumple con los filtros.
        La instancia de Proceso contiene los documentos creados dentro de él.
        El documento de servicio no contiene todos los datos, y una referencia a
            la tabla que contiene el complemento no es práctica, por lo que el
            complemento se carga independientemente.
    """
    proceso = man.session().query(Proceso).filter(Proceso.id==filtros['id']).one()
    # servicio = [x for x in proceso.documentos if x.tipo==u'servicio'][0]
    # complemento = man.session().query(Servicio).filter(Servicio.documento_id==servicio.id).one()
    # servicio.setComplemento(complemento)
    return proceso


def dameVarios(**filtros):
    statuss = dameStatuss()
    filtrosStatus = []

    for status in statuss:
        if str(status.valor) in filtros.keys():
            filtrosStatus.append(status.valor)

    if 'cliente_id' in filtros.keys():
        procesos = man.session().query(Proceso).filter(Proceso.tipo==u'servicio').filter(Proceso.status.in_(filtrosStatus)).order_by(Proceso.fecha.asc()).join(Documento).filter(Documento.tipo==u'servicio').filter(Documento.rol_id==filtros['cliente_id']).all()
        if 'tecnico_id' in filtros.keys():
            procesos = man.session().query(Proceso).filter(Proceso.tipo==u'servicio').filter(Proceso.status.in_(filtrosStatus)).order_by(Proceso.fecha.asc()).join(Documento).filter(Documento.tipo==u'servicio').filter(Documento.rol_id==filtros['cliente_id']).join(Servicio).filter(Servicio.tecnico_id==filtros['tecnico_id']).all()
    elif 'tecnico_id' in filtros.keys():
        procesos = man.session().query(Proceso).filter(Proceso.tipo==u'servicio').filter(Proceso.status.in_(filtrosStatus)).order_by(Proceso.fecha.asc()).join(Documento).join(Servicio).filter(Servicio.tecnico_id==filtros['tecnico_id']).all()
    else:
        if filtrosStatus:
            procesos = man.session().query(Proceso).filter(Proceso.tipo==u'servicio').filter(Proceso.status.in_(filtrosStatus)).order_by(Proceso.fecha.asc()).join(Operacion).join(Servicio).all()
        else:
            procesos = man.session().query(Proceso).filter(Proceso.tipo==u'servicio').order_by(Proceso.fecha.asc()).all()

    return procesos


# def modificaRecepcion(datos):



def modifica(datos):
    m = "servicios.manejador.modifica()"
    # print (1), m, datos

    proceso = servicioI(id=datos['id'])

    documentoServicio = [x.documentos[0] for x in proceso.operaciones if x.tipo==u'recepción'][0]

    ## RECEPCIÓN

    ##    Fecha y folio *** No se permite editarlos

    ##    Cliente       *** No se permite cambiar de cliente ni editarlo
    # if old.rol_id != datos['recepcion']['cliente'].id:
        # modificar el cliente

    ##    Equipo        *** No se permite cambiar de equipo
    ##                      Sólo se permite AGREGAR a Accesorios
        # Falta implementar

    ##    Síntomas      *** Sólo se permite AGREGAR a Síntomas

    ## DIAGNÓSTICO      *** Sólo se permite AGREGAR
    ##                      Se agrega Técnico y fecha al texto anterior en caso
    ##                          de que no lo tenga, y al nuevo texto se le incluye
    servicio = documentoServicio.servicio
    if servicio.fechadiagnostico != datos['diagnóstico']['fecha']:
        servicio.fechaDiagnostico = datos['diagnóstico']['fecha']
    if servicio.tecnico_id != datos['diagnóstico']['tecnico_id']:
        servicio.tecnico_id = datos['diagnóstico']['tecnico_id']
    if servicio.diagnostico != datos['diagnóstico']['diagnostico']:
        servicio.diagnostico = datos['diagnóstico']['diagnostico']


    ## PRESUPUESTO      *** Cómo se determina si es adecuado?
    ##                  Faltaría registrar quién lo hizo y quién lo modificó y
    ##                      cuales fueron las modificaciones

    if 'presupuesto' in datos.keys():

        operacion = operacionI(tipo=u'solicitud', cuenta=u'inventarios', fecha=datos['presupuesto']['fecha'], monto=datos['presupuesto']['total'], status=u'abierta', proceso=proceso)

        # operacion = dameOperacion(tipo=u'solicitud', proceso_id=proceso.id)

        # if not operacion:
            # operacion = operacionI(tipo=u'solicitud', cuenta=u'inventarios', fecha=pedido['fecha'], monto=pedido['total'], status=u'abierta', proceso=proceso)
            # man.session().add(operacion)
            # mans.session().flush()

        tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=u"pedido")

        documento = dameDocumento(operacion_id=operacion.id, tipo_id=tipoDocumento.id)

        if not documento:
            documento = Documento(operacion_id=operacion.id, tipo_id=tipoDocumento.id, folio=datos['presupuesto']['folio'], fecha=datos['presupuesto']['fecha'], rol_id=documentoServicio.rol_id, subtotal=datos['presupuesto']['subtotal'], descuento=datos['presupuesto']['descuento'], impuesto=datos['presupuesto']['impuesto'], total=datos['presupuesto']['total'], status=u'abierto')
            man.session().add(documento)
            man.session().flush()

        ## Partidas

        for item in datos['presupuesto']['partidas']:
            partida = damePartida(documento_id=documento.id, producto_id=item['producto_id'])
            if partida:
                partida.setData(cantidad=item['cantidad'], costo=item['costo'], precio=item['precio'], descuento=item['descuento'], impuesto=item['impuesto'], status=u'abierta')
            else:
                partida = PartidaDocumento(documento_id=documento.id, producto_id=item['producto_id'], cantidad=item['cantidad'], costo=item['costo'], precio=item['precio'], descuento=item['descuento'], impuesto=item['impuesto'], status=u'abierta')
                documento.partidas.append(partida)

            man.session().add(partida)
            man.session().flush()

        ## Actualiza folio
        registro = atributoI(grupo=u'folioDocumento', nombre=u'pedido', valor=datos['presupuesto']['folio'])


    ## VENTA            *** Sólo se permite AGREGAR otra venta
    if 'venta' in datos.keys():
        venta = datos['venta']

        documento = man.dameDocumento(tipo_id=venta['tipoDocumento_id'], folio=venta['folio'])

        costo = dec('0.00')

        if not documento:
            documento = Documento(tipo_id=venta['tipoDocumento_id'], folio=venta['folio'], fecha=venta['fecha'], rol_id=documentoServicio.rol_id, subtotal=venta['subtotal'], descuento=venta['descuento'], impuesto=venta['impuesto'], total=venta['total'], status=u'cerrado')
            man.session().add(documento)
            man.session().flush()

            for item in venta['partidas']:
                costo += item['costo'] * item['cantidad']
                item.update({'documento_id':documento.id})
                item.update({'status':u'cerrada'})

                partida = PartidaDocumento(**item)
                documento.partidas.append(partida)
                man.session().add(partida)
                man.session().flush()

        operacion = operacionI(tipo=u'salida', cuenta=u'inventarios', fecha=venta['fecha'], monto=-costo, status=u'cerrada', proceso=proceso)

        documento.operacion_id = operacion.id
        man.session().add(documento)
        man.session().flush()

        ##    Pago
        if venta['pago']['tipo'] == u'efectivo':
            operacionPago = operacionI(cuenta=u"caja", tipo=u'cobro', fecha=venta['fecha'], monto=venta['total'], status=u'cerrada', proceso=proceso)

            tipoDocumento = atributoI(grupo=u'tipoDocumento', nombre=venta['pago']['tipo'])

            documentoPago = Documento(operacion_id=operacionPago.id, tipo_id=tipoDocumento.id, total=venta['pago']['total'], subtotal=venta['pago']['recibido'], descuento=venta['pago']['cambio'], fecha=datetime.datetime.today(), status=u'cerrado')
            man.session().add(documentoPago)
            man.session().flush()

            proceso.status = u'cerrado'

        consolidaSalidas(documento.partidas)

        modificaFolio(datos['venta']['folio'], documento.tipo)

    man.session().commit()

    return proceso


def consolidaSalidas(partidas):
    for partida in partidas:
        producto = productoI(id=partida.producto_id)
        producto.actual -= partida.cantidad
        # if producto.actual:
            # producto.actual -= partida.cantidad
        # else:
            # producto.actual = partida.cantidad
    man.session().flush()


def modificaFolio(folio, tipoDocumento):
    if tipoDocumento == u'servicio':
        registro = atributoI(grupo=u'servicios', nombre=u'ultimoFolio', valor=unicode(folio))
    elif tipoDocumento == u'pedido':
        registro = atributoI(grupo=u'pedidos', nombre=u'ultimoFolio', valor=unicode(folio))
    elif tipoDocumento == u'remisión':
        registro = atributoI(grupo=u'ventas', nombre=u'ultimoFolioControl', valor=unicode(folio))
    elif tipoDocumento == u'factura':
        registro = atributoI(grupo=u'ventas', nombre=u'ultimoFolioFiscal', valor=unicode(folio))


# print (0), "  servicios.manejador   end"



"""

Cuando un cliente solicita que se ejecute alguna acción a un equipo de
    su propiedad.

Se crea un proceso
    id
    tipo    u"servicio"
    fecha   Actual
    status  u"abierto"

Se crea una orden de servicio (documento general con anexo de servicio):
    id
    proceso_id          proceso_id
    tipo                u"orden de servicio"
    folio               Consecutivo
    fecha               Actual
    rol_id              cliente_id
    subtotal            --
    descuento           --
    descuentoporcentaje --
    impuesto            --
    impuestoporcentaje  --
    total               --
    status              u"abierta"

    anexo de servicio
        documento_id        id
        equipo_id           equipo_id
        nivel1              x
        nivel2              x
        accesorios          x
        observaciones       x
        sintomas            x
        fechadiagnostico    x
        tecnico_id          tecnico_id
        diagnostico         x


Se crea un presupuesto (documento general con anexo de partidas):
    id
    proceso_id          proceso_id
    tipo                u"orden de compra" o u"pedido"
    folio               Consecutivo
    fecha               Actual
    rol_id              cliente_id
    subtotal            x
    descuento           x
    descuentoporcentaje x
    impuesto            x
    impuestoporcentaje  x
    total               x
    status              u"pendiente"

    partidas            x

Se crea una venta (documento general con anexo de partidas):
    id
    proceso_id          proceso_id
    tipo                u"venta"
    folio               Consecutivo
    fecha               Actual
    rol_id              cliente_id
    subtotal            x
    descuento           x
    descuentoporcentaje x
    impuesto            x
    impuestoporcentaje  x
    total               x
    status              u"pendiente"

    partidas            x



REGISTRO PROCESO
    Status      [u'Abierto', u'Cerrado', u'Cancelado']




    Orden de compra :
        Se crea al recibir un aparato para cualquier proceso.
        Contiene todos los datos descriptivos del equipo.
        Contiene todos los datos relativos al funcionamiento del equipo.
        Fecha de inicio de operación, tipo de trabajo, lugar de
            trabajo, condiciones de trabajo, operadores.
        Contiene los síntomas que presenta el equipo.
        Contiene indicaciones extras del usuario o del cliente.
        Se generan las instancias necesarias en papel.

        Diagnóstico :
            Se crea al revisar un aparato.
            Contendrá el resultado de la revisión del aparato.
        Presupuesto :
            Se crea al terminar la revision.
            Contendrá el listado de todos los productos y servicios que se
                aplicarían.
            Contendrá el listado de los productos y reparaciones que el
                cliente aceptó que se aplicaran en el servicio.
        Ejecución :
            Se crea al terminar de aplicar el servicio.

        Cada parte podrá incluir comentarios de los involucrados.

    Factura o remisión :
        Ampara el pago detallado del cliente.
        Se generan las instancias necesarias en papel.


"""